#include "colorset.h"

#include <bool.h>

#include <QtCore/QVariant>

using namespace core;
using namespace wfnet;

const TypeName ColorSet::NAME = Type::demangledName(typeid(ColorSet).name());

ColorSet::ColorSet(const ColorSet& other) : IColorSet(), ValueType(),
    m_name(other.m_name),
    m_type(dynamic_cast<ValueType*>(other.m_type->copy())),
    m_isTimed(other.m_isTimed),
    m_time(0)
{
    copySupportedOperations();
}

ColorSet::~ColorSet()
{
    delete m_type;
}

bool ColorSet::isTimed() const
{
    return m_isTimed;
}

void ColorSet::setTime(core::BasicTime& time)
{
    if (m_isTimed)
    {
        m_time = time;
    }
}

BasicTime ColorSet::getTime() const
{
    return m_time;
}

void ColorSet::setValue(const QVariant& value)
{
    m_type->setValue(value);
}

QVariant ColorSet::getValue() const
{
    return m_type->getValue();
}

QString ColorSet::name() const
{
    return m_name;
}

bool ColorSet::matches(const Type& type) const
{
    const ColorSet* other = dynamic_cast<const ColorSet *>(&type);
    return other != 0 ? other->m_type->matches(*m_type)
        && other->m_isTimed == m_isTimed :
        type.matches(*m_type);
}

bool ColorSet::matches(const TypeName& name) const
{
    return m_type->matches(name) || m_name == name || NAME == name;
}

ColorSet& ColorSet::operator=(const ColorSet& other)
{
    if (this != &other)
    {
        m_name = other.m_name;

        delete m_type;
        m_type = 0;

        m_type = dynamic_cast<ValueType*>(other.m_type->copy());
        m_isTimed = other.m_isTimed;

        copySupportedOperations();
    }

    return *this;
}

bool ColorSet::operator ==(const Type& type) const
{
    const ColorSet* other = dynamic_cast<const ColorSet *>(&type);
    return other != 0 ?
        (*m_type == *other->m_type && m_name == other->m_name &&
         other->m_isTimed == m_isTimed) : false;
}

bool ColorSet::operator !=(const Type& type) const
{
    const ColorSet* other = dynamic_cast<const ColorSet *>(&type);
    return other != 0 ?
        (*m_type != *other->m_type || m_name != other->m_name ||
        other->m_isTimed != m_isTimed) : true;
}

bool ColorSet::canConvert(const TypeValue& value) const
{
    return m_type->canConvert(value);
}

ValueKeywordMask ColorSet::keywordMask() const
{
    return m_type->keywordMask();
}

bool ColorSet::hasIdentity() const
{
    return true;
}

Type* ColorSet::copy() const
{
    ColorSet* newInstance = new ColorSet(*this);
    return newInstance;
}

TypeName ColorSet::typeOf() const
{
    return m_type->name();
}

const ValueType* ColorSet::getType() const
{
    return m_type;
}

ColorSet::ColorSet(const QString& name, const ValueType& type,
    bool isTimed) : IColorSet(), ValueType(),
    m_name(name),
    m_type(dynamic_cast<ValueType*>(type.copy())),
    m_isTimed(isTimed),
    m_time(0)
{
    copySupportedOperations();
}

void ColorSet::copySupportedOperations()
{
    const QSet<OperationName> supported = m_type->supportedOperations();

    foreach (const OperationName& operation, supported)
    {
        m_operations.insert(operation,
            QPair<TypeName, TypeName>(m_type->operationReturnType(operation),
                m_type->rightOperatorType(operation)));
    }
}

uint qHash(const wfnet::ColorSet& color)
{
    return qHash(color.getValue().toString()) ^ qHash(color.name());
}
